//导入自己编写的memberStore
import { useMemberStore } from "@/stores/modules/member"

/* 
    *添加拦截器{
        1.request（uniapp里面用来发送请求的）
        2.uploadFile（上传文件地址到服务器的）
    }
    1.非http开头需要拼接url
    2.设置请求时间
    3.设置请求头
    4.往请求头里添加token

*/

//请求基地址,这里是服务器的基地址
/* const baseURL = "http://47.108.84.95:8000/api" */
const baseURL = "http://localhost:8000/api"

//编写请求拦截器
const httpInterceptor = {
    //声明options的类型
    invoke(options:UniApp.RequestOptions){
        //1.请求地址不是以http开头的，则需要拼接url
        if(!options.url.startsWith('http')){
            options.url = baseURL + options.url
        }
        //2.设置请求时间
        options.timeout = 600000
        //3.设置请求头
        options.header = {
            //这里是为了保存原来存在的请求头
            //...语法是ES6里面的拓展运算符
            ...options.header,
            //设置为小程序,如果后端需要则设置，不需要则不设置
            'source-client':'miniapp',
        }
        //4.往请求头header里设置token
        const memberStore = useMemberStore()
        //可选链语法，如果userInfo存在，再进行下一步的操作
        const token = memberStore?.token
        if(token)
        {
            options.header.Authorization = token
        }
    }
}
//向request，uploadFile增加请求拦截器
uni.addInterceptor('request',httpInterceptor)
uni.addInterceptor('uploadFile',httpInterceptor)
/**
 * 请求函数
 * @param  UniApp.RequestOptions
 * @returns Promise
 *  1. 返回 Promise 对象，用于处理返回值类型
 *  2. 获取数据成功
 *    2.1 提取核心数据 res.data
 *    2.2 添加类型，支持泛型
 *  3. 获取数据失败
 *    3.1 401错误  -> 清理用户信息，跳转到登录页
 *    3.2 其他错误 -> 根据后端错误信息轻提示
 *    3.3 网络错误 -> 提示用户换网络
 */

//定义后端返回给我们数据的类型，这里要根据后端实际返回的类型，仅供参考
//这样定义只是为了让数据的类型更加严谨
interface Data<T>
{
    code:string,
    msg:string,
    result:T
}

//类似于axios里面的响应拦截器
export const http = <T>(options:UniApp.RequestOptions)=>{
    return new Promise<Data<T>>((resolve,reject) => {
        uni.request({
            //options里面包含了url，method，params
            //扩展运算符，类似于解构赋值，将options里面的成员变量解构出来
            ...options,
            //响应成功执行回调函数
            //res为形参
            success(res){
                //后端返回的状态码，200表示请求数据成功
                if(res.statusCode === 200)
                {
                    //提取核心数据
                    //这里的data是后端返回的那一部分数据
                    //声明res.data为自己定义的类型
                    resolve(res.data as Data<T>)
                }
                else if(res.statusCode === 401)
                {
                    //401错误，后端返回的
                    //清除用户信息
                    const memberStore = useMemberStore()
                    memberStore.cleanUserInfo()
                    //跳转到登录页，提醒用户登录
                    uni.navigateTo({url:'/pages/my/my'})
                    reject(res)//标记为失败，不让函数继续执行
                }else{
                    //其他错误，根据后端返回的错误提示展现到页面上
                    uni.showToast({
                        //提示框的图片显示none
                        icon:'none',
                        title:res.data.msg || '请求错误'//msg是后端返回的错误信息，如果没有返回则使用自己写的“请求错误”
                    })
                    reject(res)
                }
            },
            //响应失败
            fail(err){
                /* uni.showToast官网
                 * url:https://uniapp.dcloud.net.cn/api/ui/prompt.html#showtoast
                 */
                uni.showToast({
                    title: '网络故障，换个网络重新试试',
                    icon: 'none'
                })
                reject(err)
            }
        })
    })
}